package com.chrray.position.util.ffmpeg;


import lombok.extern.slf4j.Slf4j;
import ws.schild.jave.Encoder;
import ws.schild.jave.EncoderException;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.stream.Collectors;

/**
 * @author LM
 * @date 2023/8/8 15:03
 */
@Slf4j
public class FfmpegUtil {

    /**
     * 通过本地路径获取多媒体文件信息(宽，高，时长，编码等)
     *
     * @param localPath 本地路径
     * @return MultimediaInfo 对象,包含 (宽，高，时长，编码等)
     * @throws EncoderException
     */
    public static MultimediaInfo getMultimediaInfo(String localPath) {
        MultimediaInfo multimediaInfo = null;
        try {
            multimediaInfo = new MultimediaObject(new File(localPath)).getInfo();
        } catch (EncoderException e) {
            System.out.println("获取多媒体文件信息异常");
            e.printStackTrace();
        }
        return multimediaInfo;
    }

    /**
     * 通过URL获取多媒体文件信息
     *
     * @param url 网络url
     * @return MultimediaInfo 对象,包含 (宽，高，时长，编码等)
     * @throws EncoderException
     */
    public static MultimediaInfo getMultimediaInfoFromUrl(String url) {
        MultimediaInfo multimediaInfo = null;
        try {
            multimediaInfo = new MultimediaObject(new URL(url)).getInfo();
        } catch (Exception e) {
            System.out.println("获取多媒体文件信息异常");
            e.printStackTrace();
        }
        return multimediaInfo;
    }

    private static final int SAMPLING_RATE = 16000;
    private static final int SINGLE_CHANNEL = 1;

    /**
     * 音频格式化为wav,并设置单声道和采样率
     *
     * @param url        需要转格式的音频
     * @param targetPath 格式化后要保存的目标路径
     */
    public static boolean formatAudio(String url, String targetPath) {
        File target = new File(targetPath);
        MultimediaObject multimediaObject;
        try {
            // 若是本地文件： multimediaObject = new MultimediaObject(new File("你的本地路径"));
            multimediaObject = new MultimediaObject(new URL(url));
            // 音频参数
            // TODO: 2023/1/31 此处按需自定义音频参数
            AudioAttributes audio = new AudioAttributes();
            // 采样率
            audio.setSamplingRate(SAMPLING_RATE);
            // 单声道
            audio.setChannels(SINGLE_CHANNEL);
            Encoder encoder = new Encoder();
            EncodingAttributes attrs = new EncodingAttributes();
            // 输出格式
            attrs.setOutputFormat("wav");
            attrs.setAudioAttributes(audio);
            encoder.encode(multimediaObject, target, attrs);
            return true;
        } catch (Exception e) {
            System.out.println("格式化音频异常");
            return false;
        }
    }

    /**
     * 视频格式化为mp4
     *
     * @param url
     * @param targetPath
     * @return
     */
    public static boolean formatToMp4(String url, String targetPath) {
        File target = new File(targetPath);
        MultimediaObject multimediaObject;
        try {
            // 若是本地文件： multimediaObject = new MultimediaObject(new File("你的本地路径"));
            multimediaObject = new MultimediaObject(new URL(url));
            EncodingAttributes attributes = new EncodingAttributes();
            // 设置视频的音频参数
            AudioAttributes audioAttributes = new AudioAttributes();
            attributes.setAudioAttributes(audioAttributes);
            // 设置视频的视频参数
            VideoAttributes videoAttributes = new VideoAttributes();
            // 设置帧率
            videoAttributes.setFrameRate(25);
            attributes.setVideoAttributes(videoAttributes);
            // 设置输出格式
            attributes.setOutputFormat("mp4");
            Encoder encoder = new Encoder();
            encoder.encode(multimediaObject, target, attributes);
            return true;
        } catch (Exception e) {
            System.out.println("格式化视频异常");
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取视频缩略图 获取视频第0秒的第一帧图片
     *
     * <p>执行的ffmpeg 命令为： ffmpeg -i 你的视频文件路径 -ss 指定的秒数 生成文件的全路径地址
     *
     * @param localPath  本地路径
     * @param targetPath 存放的目标路径
     * @return
     */
    public static boolean getTargetThumbnail(String localPath, String targetPath) {
        // FIXME: 2023/1/31  该方法基本可作为执行ffmpeg命令的模板方法，之后的几个方法与此类似
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            ffmpeg.addArgument("-ss");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument("0");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("获取视频缩略图失败");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 等待命令执行成功，退出
     *
     * @param br
     * @throws IOException
     */
    private static void blockFfmpeg(BufferedReader br) throws IOException {
        String line;
        // 该方法阻塞线程，直至合成成功
        while ((line = br.readLine()) != null) {
            doNothing(line);
        }
    }

    /**
     * 打印日志
     *
     * @param line
     */
    private static void doNothing(String line) {
        // FIXME: 2023/1/31 正式使用时注释掉此行，仅用于观察日志
        System.out.println(line);
    }

    /**
     * 视频增加字幕
     *
     * @param originVideoPath 原视频地址
     * @param targetVideoPath 目标视频地址
     * @param srtPath         固定格式的srt文件地址或存储位置，字母文件名： xxx.srt，样例看博客
     * @return
     * @throws Exception
     */
    public static boolean addSubtitle(
            String originVideoPath, String srtPath, String targetVideoPath) {
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(originVideoPath);
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(srtPath);
            ffmpeg.addArgument("-c");
            ffmpeg.addArgument("copy");
            ffmpeg.addArgument(targetVideoPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("字幕增加失败");
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 常用命令
     *
     * @return
     */
    public static void cmd() {
        // FIXME: 2023/1/31  还有很多类似命令 不再一一列举 ，附上命令,具体写法参考 getTargetThumbnail或addSubtitle方法
        // FIXME: 2023/1/31 ffmpeg命令网上搜索即可

        // 剪切视频
        // ffmpeg -ss 00:00:00 -t 00:00:30 -i test.mp4 -vcodec copy -acodec copy output.mp4
        // * -ss 指定从什么时间开始
        // * -t 指定需要截取多长时间
        // * -i 指定输入文件

        // ffmpeg -ss 10 -t 15 -accurate_seek -i test.mp4 -codec copy cut.mp4
        // ffmpeg -ss 10 -t 15 -accurate_seek -i test.mp4 -codec copy -avoid_negative_ts 1 cut.mp4

        // 拼接MP4
        // 第一种方法：
        // ffmpeg -i "concat:1.mp4|2.mp4|3.mp4" -codec copy out_mp4.mp4
        // 1.mp4 第一个视频文件的全路径
        // 2.mp4 第二个视频文件的全路径

        // 提取视频中的音频
        // ffmpeg -i input.mp4 -acodec copy -vn output.mp3
        // -vn: 去掉视频；-acodec: 音频选项， 一般后面加copy表示拷贝

        // 音视频合成
        // ffmpeg -y –i input.mp4 –i input.mp3 –vcodec copy –acodec copy output.mp4
        // -y 覆盖输出文件

        // 剪切视频
        //  ffmpeg -ss 0:1:30 -t 0:0:20 -i input.mp4 -vcodec copy -acodec copy output.mp4
        // -ss 开始时间; -t 持续时间

        // 视频截图
        //  ffmpeg –i test.mp4 –f image2 -t 0.001 -s 320x240 image-%3d.jpg
        // -s 设置分辨率; -f 强迫采用格式fmt;

        // 视频分解为图片
        //   ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg
        // -r 指定截屏频率

        // 将图片合成视频
        //  ffmpeg -f image2 -i image%d.jpg output.mp4

        // 视频拼接
        //  ffmpeg -f concat -i filelist.txt -c copy output.mp4

        // 将视频转为gif
        //    ffmpeg -i input.mp4 -ss 0:0:30 -t 10 -s 320x240 -pix_fmt rgb24 output.gif
        // -pix_fmt 指定编码

        // 视频添加水印
        //  ffmpeg -i input.mp4 -i logo.jpg
        // -filter_complex[0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map
        // 0:a -codec:a copy output.mp4
        // main_w-overlay_w-10 视频的宽度-水印的宽度-水印边距；

    }

    /**
     * 拼接视频
     *
     * @param localPath1 原视频1
     * @param localPath2 原视频2
     * @param targetPath 输出视频
     * @return
     */
    public static boolean merge(String localPath1, String localPath2, String targetPath) {
        // Fffmpeg -f concat -i "concat:01.mp4|02.mp4" -c copy output.mp4
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-f");
            ffmpeg.addArgument("concat");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument("\"concat:");
            ffmpeg.addArgument(localPath1);
            ffmpeg.addArgument("|");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument(localPath2);
            ffmpeg.addArgument("\"");
            ffmpeg.addArgument("-c");
            ffmpeg.addArgument("copy");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("拼接视频失败");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 叠加视频
     *
     * @param localPath1 主视频
     * @param localPath2 叠加视频
     * @param targetPath 输出视频
     * @return
     */
    public static boolean overlay(String localPath1, String localPath2, String targetPath) {
        // ffmpeg -i 2160-1.mp4 -i 31.mov  -filter_complex "[0][1]overlay=alpha=1"  -y output12.mp4
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath1);
            ffmpeg.addArgument("-i");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument(localPath2);
            ffmpeg.addArgument("-filter_complex");
            ffmpeg.addArgument("\"[0][1]overlay=alpha=1\"");
            ffmpeg.addArgument("-y");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("叠加视频失败");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 截取视频
     *
     * @param localPath  主视频
     * @param startTime  开始截取时间
     * @param endTime    结束截取时间
     * @param targetPath 输出视频
     * @return
     */
    public static boolean cutOut(String localPath, String startTime, String endTime, String targetPath) {
        // ffmpeg -i 720-2.mp4 -ss 00:50 -to 00:54 -c:v libx264 -crf 30 720-3.mp4
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            ffmpeg.addArgument("-ss");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument(startTime);
            ffmpeg.addArgument("-to");
            ffmpeg.addArgument(endTime);
            ffmpeg.addArgument("-c:v");
            ffmpeg.addArgument("libx264 ");
            ffmpeg.addArgument("-crf");
            ffmpeg.addArgument("30");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("截取视频失败");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 水印
     *
     * @param localPath  视频地址
     * @param picFileUrl 图片文件地址
     * @param abscissa   横坐标
     * @param vertical   纵坐标
     * @param targetPath 输出视频
     * @return
     */
    public static boolean watermark(String localPath, String picFileUrl, String abscissa, String vertical, String targetPath) {
        // ffmpeg -i output8.mp4 -vf "movie=2-1/1_%05d.png:loop=5,setpts=N/FRAME_RATE/TB[logo];[0:v][logo]overlay=x=400:y=500"  -y output11.mp4
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            ffmpeg.addArgument("-vf");
            ffmpeg.addArgument("\"movie=");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument(picFileUrl);
            ffmpeg.addArgument(":loop=5,setpts=N/FRAME_RATE/TB[logo];[0:v][logo]overlay=x=");
            ffmpeg.addArgument(abscissa);
            ffmpeg.addArgument(":y=");
            ffmpeg.addArgument(vertical);
            ffmpeg.addArgument("\"");
            ffmpeg.addArgument("-y");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("截取视频失败");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 截取片段
     *
     * @param localPath  addArgument 字符串不能有空格
     * @param targetPath
     * @param startTime
     * @param toTime
     * @return
     */
    public static boolean sub265(String localPath, String targetPath, String startTime, String toTime) {
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            ffmpeg.addArgument("-ss");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument(startTime);
            ffmpeg.addArgument("-t");
            ffmpeg.addArgument(toTime);
            ffmpeg.addArgument("-c:v");
            ffmpeg.addArgument("libx264");
            ffmpeg.addArgument("-crf");
            ffmpeg.addArgument("30");
            ffmpeg.addArgument("-y");
            ffmpeg.addArgument(targetPath);

            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }


        } catch (IOException e) {
            System.out.println("截取指定时间视频");
            e.printStackTrace();
            return false;
        }
        return true;


    }

    /**
     * ffmpeg -i "concat:/xxx/a.ts|/xxx/b.ts" -c copy c.mp4
     *
     * @param localPath
     * @param targetPath
     * @return
     */
    public static boolean concatFile(String localPath, String targetPath) {
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-f");
            ffmpeg.addArgument("concat");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            // 此处可自定义视频的秒数
            ffmpeg.addArgument("-c");
            ffmpeg.addArgument("copy");
            ffmpeg.addArgument("-y");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("拼接视频完成");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 添加音频
     * ffmpeg -i a13.mp4 -i  vn.mp3 -vcodec copy -acodec copy a14.mp4
     *
     * @param localPath  视频地址
     * @param anPath     音频地址
     * @param targetPath 输出地址
     * @return
     */
    public static boolean addAn(String localPath, String anPath, String targetPath) {
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(anPath);
            ffmpeg.addArgument("-vcodec");
            ffmpeg.addArgument("copy");
            ffmpeg.addArgument("-acodec");
            ffmpeg.addArgument("copy");
            ffmpeg.addArgument("-y");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("添加音频");
            e.printStackTrace();
            return false;
        }
        return true;
    }


    /**
     * 模板1   (双引号要单独占一行)
     * ffmpeg -i a1.mp4 -i 3/demo1_%05d.png  -i 1/Scene_1_%05d.png   -itsoffset 1 -start_number 30 -i 2/1-2_%05d.png
     * -i 4/Scene_1_%05d.png  -itsoffset 2 -start_number 59 -i 7/Scene_2_%05d.png -itsoffset 2 -start_number 59 -i 5/Scene_2_%05d.png
     * -itsoffset 2 -start_number 59 -i 6/Scene_2_%05d.png -itsoffset 4 -start_number 313 -i 9/demo1_%05d.png
     * -itsoffset 4  -i 8/1_00314.png   -itsoffset 7  -start_number 409 -i 10/demo1_%05d.png  -itsoffset 11
     * -i 11/demo1_%05d.png -filter_complex "[0][1]overlay=x=0:y=0:enable='between(t,0,1)'[v1];
     * [v1][2]overlay=x=0:y=0:enable='between(t,0,1)'[v2];[v2][3]overlay=x=0:y=0:enable='between(t,1,2)'[v3];
     * [v3][4]overlay=x=0:y=0:enable='between(t,0,2)'[v4];[v4][5]overlay=x=0:y=0:enable='between(t,2,4)'[v5];
     * [v5][6]overlay=x=0:y=0:enable='between(t,2,4)'[v6];[v6][7]overlay=x=0:y=0:enable='between(t,2,4)'[v7];
     * [v7][8]overlay=x=0:y=0:enable='between(t,4,7)'[v8];[v8][9]overlay=x=0:y=0:enable='between(t,4,7)'[v9];
     * [v9][10]overlay=x=0:y=0:enable='between(t,7,11)'[v10];[v10][11]overlay=x=0:y=0:enable='between(t,11,14)'[v11]"
     * -map "[v11]" -map 0:a   vv1.mp4
     *
     * @param localPath
     * @param targetPath
     * @param picPage
     * @return
     */
    public static boolean moudle1(String localPath, String targetPath, String picPage) {
        try {
            ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor();
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(localPath);
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page1);
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page2);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("1");
            ffmpeg.addArgument("-start_number");
            ffmpeg.addArgument("30");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page3);
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page4);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("2");
            ffmpeg.addArgument("-start_number");
            ffmpeg.addArgument("59");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page5);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("2");
            ffmpeg.addArgument("-start_number");
            ffmpeg.addArgument("59");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page6);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("2");
            ffmpeg.addArgument("-start_number");
            ffmpeg.addArgument("59");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page7);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("4");
            ffmpeg.addArgument("-start_number");
            ffmpeg.addArgument("313");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page8);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("4");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page9);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("7");
            ffmpeg.addArgument("-start_number");
            ffmpeg.addArgument("409");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page10);
            ffmpeg.addArgument("-itsoffset");
            ffmpeg.addArgument("11");
            ffmpeg.addArgument("-i");
            ffmpeg.addArgument(picPage + "/" + MoudleVideo1.page11);
            ffmpeg.addArgument("-filter_complex");

         /*   String s="\0x22[0][1]overlay=x=0:y=0:enable='between(t,0,1)'[v1];[v1][2]overlay=x=0:y=0:enable='between(t,0,1)'[v2];[v2][3]overlay=x=0:y=0:enable='between(t,1,2)'[v3];"+
                    "[v3][4]overlay=x=0:y=0:enable='between(t,0,2)'[v4];[v4][5]overlay=x=0:y=0:enable='between(t,2,4)'[v5];"+
                    "[v5][6]overlay=x=0:y=0:enable='between(t,2,4)'[v6];[v6][7]overlay=x=0:y=0:enable='between(t,2,4)'[v7];"+"" +
                    "[v7][8]overlay=x=0:y=0:enable='between(t,4,7)'[v8];[v8][9]overlay=x=0:y=0:enable='between(t,4,7)'[v9];"+
                    "[v9][10]overlay=x=0:y=0:enable='between(t,7,11)'[v10];[v10][11]overlay=x=0:y=0:enable='between(t,11,14)'[v11]\0x22";

            */

            ffmpeg.addArgument("\"[0][1]overlay=x=0:y=0:enable='between(t,0,1)'[v1];");
            ffmpeg.addArgument("[v1][2]overlay=x=0:y=0:enable='between(t,0,1)'[v2];[v2][3]overlay=x=0:y=0:enable='between(t,1,2)'[v3];");
            ffmpeg.addArgument("[v3][4]overlay=x=0:y=0:enable='between(t,0,2)'[v4];[v4][5]overlay=x=0:y=0:enable='between(t,2,4)'[v5];");
            ffmpeg.addArgument("[v5][6]overlay=x=0:y=0:enable='between(t,2,4)'[v6];[v6][7]overlay=x=0:y=0:enable='between(t,2,4)'[v7];");
            ffmpeg.addArgument("[v7][8]overlay=x=0:y=0:enable='between(t,4,7)'[v8];[v8][9]overlay=x=0:y=0:enable='between(t,4,7)'[v9];");
            ffmpeg.addArgument("[v9][10]overlay=x=0:y=0:enable='between(t,7,11)'[v10];[v10][11]overlay=x=0:y=0:enable='between(t,11,14)'[v11]\"");
            ffmpeg.addArgument("-map");
            ffmpeg.addArgument("\"[v11]\"");
            ffmpeg.addArgument("-threads");
            ffmpeg.addArgument("4");
            ffmpeg.addArgument("-map");
            ffmpeg.addArgument("0:a");
            // 此处可自定义视频的秒数
            ffmpeg.addArgument("-y");
            ffmpeg.addArgument(targetPath);
            ffmpeg.execute();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
                blockFfmpeg(br);
            }
        } catch (IOException e) {
            System.out.println("模板1生成完成");
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static boolean newMoudle1(String localPath, String targetPath, String picPage) {
        try {
            ArrayList<String> ffmpeg = new ArrayList();
            ffmpeg.add("ffmpeg");
            ffmpeg.add("-i");
            ffmpeg.add(localPath);
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page1);
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page2);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("1");
            ffmpeg.add("-start_number");
            ffmpeg.add("30");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page3);
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page4);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("2");
            ffmpeg.add("-start_number");
            ffmpeg.add("59");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page5);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("2");
            ffmpeg.add("-start_number");
            ffmpeg.add("59");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page6);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("2");
            ffmpeg.add("-start_number");
            ffmpeg.add("59");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page7);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("4");
            ffmpeg.add("-start_number");
            ffmpeg.add("313");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page8);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("4");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page9);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("7");
            ffmpeg.add("-start_number");
            ffmpeg.add("409");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page10);
            ffmpeg.add("-itsoffset");
            ffmpeg.add("11");
            ffmpeg.add("-i");
            ffmpeg.add(picPage + "/" + MoudleVideo1.page11);
            ffmpeg.add("-filter_complex");

         /*   String s="\0x22[0][1]overlay=x=0:y=0:enable='between(t,0,1)'[v1];[v1][2]overlay=x=0:y=0:enable='between(t,0,1)'[v2];[v2][3]overlay=x=0:y=0:enable='between(t,1,2)'[v3];"+
                    "[v3][4]overlay=x=0:y=0:enable='between(t,0,2)'[v4];[v4][5]overlay=x=0:y=0:enable='between(t,2,4)'[v5];"+
                    "[v5][6]overlay=x=0:y=0:enable='between(t,2,4)'[v6];[v6][7]overlay=x=0:y=0:enable='between(t,2,4)'[v7];"+"" +
                    "[v7][8]overlay=x=0:y=0:enable='between(t,4,7)'[v8];[v8][9]overlay=x=0:y=0:enable='between(t,4,7)'[v9];"+
                    "[v9][10]overlay=x=0:y=0:enable='between(t,7,11)'[v10];[v10][11]overlay=x=0:y=0:enable='between(t,11,14)'[v11]\0x22";

            */

            ffmpeg.add("\"[0][1]overlay=x=0:y=0:enable='between(t,0,1)'[v1];");
            ffmpeg.add("[v1][2]overlay=x=0:y=0:enable='between(t,0,1)'[v2];[v2][3]overlay=x=0:y=0:enable='between(t,1,2)'[v3];");
            ffmpeg.add("[v3][4]overlay=x=0:y=0:enable='between(t,0,2)'[v4];[v4][5]overlay=x=0:y=0:enable='between(t,2,4)'[v5];");
            ffmpeg.add("[v5][6]overlay=x=0:y=0:enable='between(t,2,4)'[v6];[v6][7]overlay=x=0:y=0:enable='between(t,2,4)'[v7];");
            ffmpeg.add("[v7][8]overlay=x=0:y=0:enable='between(t,4,7)'[v8];[v8][9]overlay=x=0:y=0:enable='between(t,4,7)'[v9];");
            ffmpeg.add("[v9][10]overlay=x=0:y=0:enable='between(t,7,11)'[v10];[v10][11]overlay=x=0:y=0:enable='between(t,11,14)'[v11]\"");
            ffmpeg.add("-map");
            ffmpeg.add("\"[v11]\"");
            ffmpeg.add("-threads");
            ffmpeg.add("2");
            ffmpeg.add("-map");
            ffmpeg.add("0:a");
            // 此处可自定义视频的秒数
            ffmpeg.add("-y");
            ffmpeg.add(targetPath);
            ffmpeg.add("-hide_banner");
            String s = ffmpeg.stream().collect(Collectors.joining(" "));
            log.info("模板1生成语句：{}",s);
            Process process = Runtime.getRuntime().exec(new String[]{"sh", "-c", s});
            try {
                process.waitFor();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                blockFfmpeg(br);
            }


        } catch (IOException e) {
            System.out.println("模板1生成完成");
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

